﻿
//编译器类--把源程序编译为汇编程序
namespace n_VM_Assembler
{
using System;
using System.Text;
using n_Compiler;
using i_Compiler;
using n_ET;
using n_OS;
using n_Decode;
using n_Config;

public static class VM_Assembler
{
	//编译器启动初始化,加载汇编运算库文件
	public static void LoadFile()
	{
		//加载运算信息表
		string s = i_Compiler.Compiler.OpenCompileFile( n_Config.Config.Path_compiler + "CPU" + OS.PATH_S + "VM" + OS.PATH_S + "hexcode.lst" );
		s = s.Remove( s.IndexOf( "\n<end>" ) );
		string[] Lines = s.Split( '\n' );
		HEXList = new string[ Lines.Length ][];
		for( int i = 0; i < Lines.Length; ++i ) {
			HEXList[ i ] = Lines[ i ].Remove( Lines[ i ].IndexOf( "<<<<" ) ).Split( '\\' );
		}
		
		n_Decode.Decode.Init();
	}
	
	//编译汇编文件
	public static string Assemble( string Source, int Index )
	{
		n_Compiler.Compiler.CompilingStep( n_Compiler.Compiler.STEP_InitAssemble );
		
		//初始化标号列表
		VLabelList.Reset();
		
		string[] Cut = Source.Split( '\n' );
		
		n_Compiler.Compiler.CompilingStep( n_Compiler.Compiler.STEP_Assemble );
		
		//提取标号
		int LabelNumber = 0;
		int StartPC = -1;
		for( int i = 0; i < Cut.Length; ++i ) {
			string Ins = Cut[ i ].Trim( ' ' );
			if( Ins == "指令区" ) {
				StartPC = i + 1;
			}
			if( Ins.StartsWith( ";" ) || Ins == "" || Ins.StartsWith( "includelib " ) ) {
				Cut[ i ] = null;
				++LabelNumber;
				continue;
			}
			if( Ins.StartsWith( "标号 " ) ) {
				string Label = Ins.Remove( 0, Ins.IndexOf( ' ' ) + 1 );
				VLabelList.Add( Label, i - LabelNumber );
				++LabelNumber;
				Cut[ i ] = null;
				continue;
			}
		}
		//定位标号
		StringBuilder Result = new StringBuilder( "" );
		for( int i = 0; i < Cut.Length; ++i ) {
			string Ins = Cut[ i ];
			if( Ins == null ) {
				continue;
			}
			string[] Args = Ins.Split( ' ' );
			int LineIndex = -1;
			if( Args[ 0 ] == "跳转" ) {
				LineIndex = VLabelList.GetLineNumber( Args[ 1 ] );
			}
			else if( Args[ 0 ].StartsWith( "分支比较_" ) ) {
				Args[ 0 ] += " " + Args[ 1 ];
				LineIndex = VLabelList.GetLineNumber( Args[ 2 ] );
			}
			else if( Args[ 0 ].StartsWith( "肯定跳转_" ) ) {
				LineIndex = VLabelList.GetLineNumber( Args[ 1 ] );
			}
			else if( Args[ 0 ].StartsWith( "否定跳转_" ) ) {
				LineIndex = VLabelList.GetLineNumber( Args[ 1 ] );
			}
			else if( Args[ 0 ].StartsWith( "跳转递减_" ) ) {
			 	LineIndex = VLabelList.GetLineNumber( Args[ 1 ] );
			}
			else if( Args[ 0 ] == "函数调用" ) {
				LineIndex = VLabelList.GetLineNumber( Args[ 1 ] );
			}
			else if( Args[ 0 ] == "函数地址_uint16" ) {
				LineIndex = VLabelList.GetLineNumber( Args[ 1 ] );
			}
			else if( Args[ 0 ] == "标签地址_uint16" ) {
				LineIndex = VLabelList.GetLineNumber( Args[ 1 ] );
			}
			else if( Args[ 0 ] == "函数地址_uint24" ) {
				LineIndex = VLabelList.GetLineNumber( Args[ 1 ] );
			}
			else if( Args[ 0 ] == "标签地址_uint24" ) {
				LineIndex = VLabelList.GetLineNumber( Args[ 1 ] );
			}
			else if( Args[ 0 ] == "函数地址_uint32" ) {
				LineIndex = VLabelList.GetLineNumber( Args[ 1 ] );
			}
			else if( Args[ 0 ] == "标签地址_uint32" ) {
				LineIndex = VLabelList.GetLineNumber( Args[ 1 ] );
			}
			else {
				Result.Append( Ins + "\n" );
				continue;
			}
			if( LineIndex == -1 ) {
				//ET.ShowError( "<VM_Assemble> 未定义的标号: " + Args[ 1 ] + " 位于指令: " + Ins );
				ET.WriteLineError( 0, 0, "<VM_Assemble> 未定义的标号: " + Args[ 1 ] + " 位于指令: " + Ins );
				continue;
			}
			Ins = Args[ 0 ] + " " + LineIndex;
			Result.Append( Ins + "\n" );
		}
		return Decode.SetInsList( Result.ToString() );
	}
	
	static string[][] HEXList;
}
public static class VLabelList
{
	public static void Reset()
	{
		LabelSet = new VLabelNode[ 10000 ];
		Length = 0;
	}
	
	//添加一个标号
	public static void Add( string Name, int LineNumber )
	{
		LabelSet[ Length ] = new VLabelNode( Name, LineNumber );
		++Length;
	}
	
	//获取某个标号的行号
	public static int GetLineNumber( string Name )
	{
		for( int i = 0; i < Length; ++i ) {
			
			if( LabelSet[ i ].Name == Name ) {
				return LabelSet[ i ].LineNumber;
			}
		}
		return -1;
	}
	
	//获取每个标号对应的行号
	public static string Show()
	{
		string s = "";
		for( int i = 0; i < Length; ++i ) {
			
			int addr = Decode.InsList[LabelSet[ i ].LineNumber].InsAddr;
			
			s += LabelSet[ i ].Name + ":" + addr + "\n";
		}
		return s;
	}
	
	static int Length;
	static VLabelNode[] LabelSet;
}
class VLabelNode
{
	public VLabelNode( string vName, int vLineNumber )
	{
		Name = vName;
		LineNumber = vLineNumber;
	}
	
	public string Name;
	public int LineNumber;
}
}

